﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine.SceneControl;

namespace PloobsEngine.Material
{
    /// <summary>
    /// Repositorio de Impostors , Uso Global
    /// </summary>
    internal class ImpostorsBank
    {

        internal static void Initiate(EngineStuff eng)
        {
            engine = eng;
            targetImpostor = EngineStuff.GetDefaultBuffer(resolution , resolution , SurfaceFormat.Color);
            depthImpostor = EngineStuff.GetDefaultDepthStencil(resolution , resolution , DepthFormat.Depth24);
        }

        private static int resolution = 128 ;

        public static void SetResolution(int valor)
        {
            resolution = valor;
            targetImpostor = EngineStuff.GetDefaultBuffer(resolution, resolution, SurfaceFormat.Color);
            depthImpostor = EngineStuff.GetDefaultDepthStencil(resolution, resolution, DepthFormat.Depth24);
        }

        static Dictionary<String, Texture2D[]> impostoresDic = new Dictionary<string, Texture2D[]>();

        public static Dictionary<String, Texture2D[]> ImpostoresDictionary
        {
            get { return ImpostorsBank.impostoresDic; }
            set { ImpostorsBank.impostoresDic = value; }
        }

        static RenderTarget2D targetImpostor;
        static DepthStencilBuffer depthImpostor;
        static EngineStuff engine;

        public static void CreateImpostores(IObject obj)
        {
            if (impostoresDic.ContainsKey(obj.Modelo.Name))
                return;

            Matrix vista;
            Matrix proyeccion = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, 3.0f/4.0f, 1.0f, 1000.0f);            
            //Matrix proyeccion = Matrix.CreateOrthographic(15,15,1,1000);            
            byte[] temp = new byte[resolution * resolution  * 4];
            Texture2D[] impostores = new Texture2D[8];

            // CameraPosicao            
            //Vector3 camaraImpostor = new Vector3(0.0f, 50.0f, 135.0f);
            Vector3 camaraImpostor = new Vector3(0.0f, 60.0f, 185.0f);
            //Vector3 camaraImpostor = obj.Modelo.GetBoudingSphere().Center + Vector3.UnitX * obj.Modelo.GetBoudingSphere().Radius;
            

            DepthStencilBuffer old = EngineStuff.GraphicsDevice.DepthStencilBuffer;
            EngineStuff.GraphicsDevice.DepthStencilBuffer = depthImpostor;

            for (int i = 0; i < 8; i++)
            {                
                EngineStuff.GraphicsDevice.SetRenderTarget(0, targetImpostor);
                EngineStuff.GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Target, Color.TransparentBlack, 1.0f, 0);
             
                Matrix rotacionCamara = Matrix.CreateRotationY(MathHelper.PiOver4 * i);
                vista = Matrix.CreateLookAt(camaraImpostor, camaraImpostor + Vector3.Forward, Vector3.Up);
             
                DrawModel(obj, vista, proyeccion, rotacionCamara);
                
                EngineStuff.GraphicsDevice.SetRenderTarget(0, null);
                impostores[i] = new Texture2D(EngineStuff.GraphicsDevice, resolution , resolution );
                targetImpostor.GetTexture().GetData<byte>(temp);
                impostores[i].SetData<byte>(temp);
                
            }
            impostoresDic.Add(obj.Modelo.Name,impostores);
            EngineStuff.GraphicsDevice.DepthStencilBuffer = old;
            EngineStuff.GraphicsDevice.RenderState.AlphaBlendEnable = false;
            EngineStuff.GraphicsDevice.RenderState.DepthBufferEnable = true;
            EngineStuff.GraphicsDevice.RenderState.DepthBufferWriteEnable = true;
        }

        private static void DrawModel(IObject model, Matrix view, Matrix projection, Matrix world)
        {
            Matrix[] transforms = model.Modelo.getBonesTransformation();            

            //foreach (ModelMesh mm in model.Modelo.getModelMeshes())
            //{
            //    foreach (BasicEffect be in mm.Effects)
            //    {
            //        be.EnableDefaultLighting();
            //        be.View = view;
            //        be.Projection = projection;
            //        be.World = transforms[mm.ParentBone.Index] * world;
            //    }
            //    mm.Draw();
            //}
        }

    }
}
